//package com.wuyou.sso2.component;
//
//import cn.hutool.core.collection.CollUtil;
//import cn.hutool.core.util.ObjectUtil;
//import cn.hutool.core.util.StrUtil;
//import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
//import com.fourport.cy.admin.api.dto.TenantDTO;
//import com.fourport.cy.admin.api.dto.TenantFeeParamDTO;
//import com.fourport.cy.admin.api.entity.Tenant;
//import com.fourport.cy.admin.api.entity.TenantOrderFlow;
//import com.fourport.cy.admin.api.service.RemoteTenantFeeParamService;
//import com.fourport.cy.admin.api.service.RemoteTenantOrderFlowService;
//import com.fourport.cy.admin.api.service.RemoteTenantService;
//import com.fourport.cy.auth.vo.ExchangeTenantVO;
//import com.fourport.cy.common.core.bean.ResultBean;
//import com.fourport.cy.common.core.component.KeyStrResolver;
//import com.fourport.cy.common.core.constant.SecurityConstants;
//import com.fourport.cy.common.security.userdetails.CustomizedUser;
//import com.fourport.cy.common.security.userdetails.TenantVO;
//import lombok.RequiredArgsConstructor;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.dubbo.config.annotation.DubboReference;
//import org.springframework.beans.BeanUtils;
//import org.springframework.data.redis.core.ConvertingCursor;
//import org.springframework.data.redis.core.Cursor;
//import org.springframework.data.redis.core.RedisTemplate;
//import org.springframework.data.redis.core.ScanOptions;
//import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
//import org.springframework.data.redis.serializer.RedisSerializer;
//import org.springframework.http.HttpHeaders;
//import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
//import org.springframework.security.core.userdetails.UserDetailsService;
//import org.springframework.security.oauth2.common.OAuth2AccessToken;
//import org.springframework.security.oauth2.common.OAuth2RefreshToken;
//import org.springframework.security.oauth2.provider.OAuth2Authentication;
//import org.springframework.security.oauth2.provider.token.TokenStore;
//import org.springframework.util.Assert;
//import org.springframework.web.bind.annotation.*;
//
//import java.util.ArrayList;
//import java.util.List;
//import java.util.stream.Collectors;
//
///**
// * 自定义token端点
// *
// * @author lishangbu
// * @date 2021/5/22
// */
//@Slf4j
//@RestController
//@RequiredArgsConstructor
//@RequestMapping("/token")
//public class CustomizedTokenEndpoint {
//
//    /**
//     * 关键字解析器
//     */
//    private final KeyStrResolver keyStrResolver;
//
//    private final RedisTemplate redisTemplate;
//
//    private final TokenStore tokenStore;
//
//    private final UserDetailsService userDetailsService;
//
//    @DubboReference(check = false)
//    private RemoteTenantService remoteTenantService;
//
//    @DubboReference(check = false)
//    private RemoteTenantFeeParamService remoteTenantFeeParamService;
//
//    @DubboReference(check = false)
//    private RemoteTenantOrderFlowService remoteTenantOrderFlowService;
//
//    /**
//     * 切换租户
//     *
//     * @param authHeader
//     * @param tenantId
//     * @return
//     */
//    @GetMapping("/update-tenant-info")
//    public ResultBean updateTenantInfo(@RequestHeader(value = HttpHeaders.AUTHORIZATION) String authHeader,
//                                       @RequestParam(value = "tenantId") Long tenantId) {
//        OAuth2AccessToken accessToken = checkToken(authHeader);
//        OAuth2Authentication auth = tokenStore.readAuthentication(accessToken);
//        CustomizedUser userDetailFromToken = (CustomizedUser) auth.getPrincipal();
//        Assert.isTrue(userDetailFromToken.getTenantList().contains(tenantId), "没有此租户的权限");
//        Tenant t = remoteTenantService.getById(tenantId);
//        Assert.isTrue(t != null, "租户不存在");
//        TenantVO vo = new TenantVO();
//        BeanUtils.copyProperties(t, vo);
//        userDetailFromToken.setTenantId(vo.getId());
//        userDetailFromToken.setTenantName(vo.getName());
//        userDetailFromToken.setCompanyCode(vo.getCompanyCode());
//        userDetailFromToken.setTenantVO(vo);
//        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
//                new UsernamePasswordAuthenticationToken(userDetailFromToken, auth.getCredentials(), auth.getAuthorities());
//        usernamePasswordAuthenticationToken.setDetails(usernamePasswordAuthenticationToken.getDetails());
//        accessToken.getAdditionalInformation().put("tenantVO", vo);
//        OAuth2Authentication oAuth2Authentication =
//                new OAuth2Authentication(auth.getOAuth2Request(), usernamePasswordAuthenticationToken);
//        tokenStore.removeAccessToken(accessToken);
//        tokenStore.storeAccessToken(accessToken, oAuth2Authentication);
//        ExchangeTenantVO result = new ExchangeTenantVO();
//        result.setTenantId(userDetailFromToken.getTenantId());
//        result.setTenantName(userDetailFromToken.getTenantName());
//        result.setCompanyCode(userDetailFromToken.getCompanyCode());
//        result.setTenantVO(vo);
//        return ResultBean.ok(result);
//    }
//
//    /**
//     * 租户修改 涉及到缓存信息变更 修改方法放置auth中
//     *
//     * @return
//     */
//    @PutMapping("/tenant-update")
//    public ResultBean<TenantDTO> tenantUpdateById(@RequestHeader(value = HttpHeaders.AUTHORIZATION) String authHeader, @RequestBody TenantDTO tenant) {
//        //处理订单类型
//        List<Integer> typeList = tenant.getTypeList();
//        List<Integer> tenantTypeList = tenant.getTenantTypeList();
//        Assert.isTrue(CollUtil.isNotEmpty(typeList), "订单类型不能为空!");
//        Assert.isTrue(CollUtil.isNotEmpty(tenantTypeList), "租户类型不能为空!");
//        Assert.notNull(tenant.getSplitFlag(), "是否支持拆托不能为空");
//        Assert.notNull(tenant.getPayFlag(), "是否支持线上支付不能为空!");
//        Assert.notNull(tenant.getUnTrayDownFlag(), "虚拟托不下架出库不能为空!");
//        //如果堆存天数上限有值，则需要判断是否大于0
//        if (ObjectUtil.isNotEmpty(tenant.getStorageUpperFlag()) && tenant.getStorageUpperFlag() && ObjectUtil.isNotEmpty(tenant.getStorageUpperLimit())) {
//            Assert.isTrue(tenant.getStorageUpperLimit() >= 0, "堆存天数上限需要大于或者等于0");
//        }
//        if (ObjectUtil.isEmpty(tenant.getStorageUpperFlag()) || !tenant.getStorageUpperFlag()) {
//            tenant.setStorageUpperLimit(null);
//        }
//        //校验
//        tenant.setOperateType(typeList.stream().map(type -> type + StrUtil.COMMA).collect(Collectors.joining()));
//        //处理租户类型
//        tenant.setTenantType(tenantTypeList.stream().map(type -> type + StrUtil.COMMA).collect(Collectors.joining()));
//        //处理绑定的仓库列表
//        List<String> warehouseList = tenant.getWarehouseList();
//        if (CollUtil.isNotEmpty(warehouseList)) {
//            tenant.setWarehouses(warehouseList.stream().map(type -> type + StrUtil.COMMA).collect(Collectors.joining()));
//        } else {
//            tenant.setWarehouses(null);
//        }
//        //处理简易流程的订单类型，这里修改是整体修改，如果简易流程为空则赋值为null
//        List<Integer> easyFlowTypeList = tenant.getEasyFlowTypeList();
//        if (CollUtil.isNotEmpty(easyFlowTypeList)) {
//            tenant.setEasyFlow(easyFlowTypeList.stream().map(type -> type + StrUtil.COMMA).collect(Collectors.joining()));
//        } else {
//            tenant.setEasyFlow(null);
//        }
//        //新的流程
//        List<TenantOrderFlow> newEasyFlowTypeList = tenant.getNewEasyFlowTypeList();
//        remoteTenantOrderFlowService.addOrUpdateQueryScheme(newEasyFlowTypeList);
//        //报文类型处理
//        List<String> messageTypeList = tenant.getMessageTypeList();
//        if (CollUtil.isNotEmpty(messageTypeList)) {
//            tenant.setMessageType(messageTypeList.stream().map(type -> type + StrUtil.COMMA).collect(Collectors.joining()));
//        } else {
//            tenant.setMessageType(null);
//        }
//        // 虚拟托不需要下架
//        if (ObjectUtil.isNotEmpty(tenant.getUnTrayDownFlag())) {
//            //不需要下架(特殊流程:库存保留库存信息)
//            tenant.setUnTrayDownFlag(tenant.getUnTrayDownFlag());
//        } else {
//            // 正常流程
//            tenant.setUnTrayDownFlag(false);
//        }
//        remoteTenantService.updateById(tenant);
//        // 修改租户费用
//        List<TenantFeeParamDTO> daysStorageCustomerList = tenant.getDaysStorageCustomerList();
//        if (CollUtil.isNotEmpty(daysStorageCustomerList)) {
//            for (TenantFeeParamDTO tenantFeeParamDTO : daysStorageCustomerList) {
//                remoteTenantService.updateDaysStorageCustomer(tenantFeeParamDTO, tenant.getId());
//            }
//        }
//        // 删除关联的租户费用设置
//        List<String> removeFeeCustomerList = tenant.getRemoveFeeCustomerList();
//        if (CollUtil.isNotEmpty(removeFeeCustomerList)) {
//            remoteTenantFeeParamService.deleteBatchIds(removeFeeCustomerList);
//        }
//        //修改缓存信息
//        OAuth2AccessToken accessToken = checkToken(authHeader);
//        OAuth2Authentication auth = tokenStore.readAuthentication(accessToken);
//        CustomizedUser userDetailFromToken = (CustomizedUser) auth.getPrincipal();
//        Assert.isTrue(userDetailFromToken.getTenantList().contains(tenant.getId()), "没有此租户的权限");
//        Tenant t = remoteTenantService.getById(tenant.getId());
//        Assert.isTrue(t != null, "租户不存在");
//        TenantVO vo = new TenantVO();
//        BeanUtils.copyProperties(t, vo);
//        userDetailFromToken.setTenantVO(vo);
//
//        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
//                new UsernamePasswordAuthenticationToken(userDetailFromToken, auth.getCredentials(), auth.getAuthorities());
//        usernamePasswordAuthenticationToken.setDetails(usernamePasswordAuthenticationToken.getDetails());
//        accessToken.getAdditionalInformation().put("tenantVO", vo);
//        OAuth2Authentication oAuth2Authentication =
//                new OAuth2Authentication(auth.getOAuth2Request(), usernamePasswordAuthenticationToken);
//        tokenStore.removeAccessToken(accessToken);
//        tokenStore.storeAccessToken(accessToken, oAuth2Authentication);
//        return ResultBean.ok(tenant, "修改成功!");
//    }
//
//    /**
//     * 删除令牌
//     *
//     * @param authHeader
//     * @param token
//     * @return
//     */
//    @DeleteMapping("/{token}")
//    public ResultBean<Boolean> delToken(@RequestHeader(value = HttpHeaders.AUTHORIZATION, required = false) String authHeader, @PathVariable("token") String token) {
//        checkToken(authHeader);
//        OAuth2AccessToken accessToken = checkToken(token);
//        // 清空access token
//        tokenStore.removeAccessToken(accessToken);
//
//
//        // 清空 refresh token
//        OAuth2RefreshToken refreshToken = accessToken.getRefreshToken();
//        if (refreshToken != null) {
//            tokenStore.removeRefreshToken(refreshToken);
//        }
//        return ResultBean.ok();
//    }
//
//    /**
//     * 退出token
//     *
//     * @param authHeader Authorization
//     */
//    @DeleteMapping("/logout")
//    public ResultBean logout(
//            @RequestHeader(value = HttpHeaders.AUTHORIZATION, required = false) String authHeader) {
//
//        OAuth2AccessToken accessToken = checkToken(authHeader);
//        // 清空access token
//        tokenStore.removeAccessToken(accessToken);
//
//        // 清空 refresh token
//        OAuth2RefreshToken refreshToken = accessToken.getRefreshToken();
//        if (refreshToken != null) {
//            tokenStore.removeRefreshToken(refreshToken);
//        }
//        return ResultBean.ok();
//    }
//
//    /**
//     * 查询token
//     *
//     * @param authHeader
//     * @param page
//     * @param userName
//     * @return
//     */
//    @GetMapping("/page")
//    public ResultBean<Page> getTokenPage(@RequestHeader(value = HttpHeaders.AUTHORIZATION, required = false) String authHeader, Page page,
//                                         @RequestParam(value = "user_name", required = false) String userName) {
//        this.checkToken(authHeader);
//        if (StrUtil.isNotBlank(userName)) {
//            return queryTokenByUsername(page, userName);
//        }
//        // 根据分页参数获取对应数据
//        String key = keyStrResolver.extract(SecurityConstants.PROJECT_PREFIX + SecurityConstants.OAUTH_PREFIX + "access:*",
//                StrUtil.COLON);
//        List<String> pages = findKeysForPage(key, page.getCurrent(), page.getSize());
//        redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
//        page.setRecords(redisTemplate.opsForValue().multiGet(pages));
//        page.setTotal(redisTemplate.keys(key).size());
//        return ResultBean.ok(page);
//    }
//
//    /**
//     * 查询token 返回list
//     *
//     * @param authHeader
//     * @param userName
//     * @return
//     */
//    @GetMapping("/list")
//    public List getTokenList(@RequestHeader(value = HttpHeaders.AUTHORIZATION, required = false) String authHeader,
//                             @RequestParam(value = "user_name", required = false) String userName) {
//        this.checkToken(authHeader);
//        String key = keyStrResolver.extract(
//                SecurityConstants.PROJECT_PREFIX + SecurityConstants.OAUTH_PREFIX + "uname_to_access_z:", StrUtil.COLON);
//        Object collect = redisTemplate.keys("*:" + userName).stream().filter(k -> ((String) k).contains(key))
//                .flatMap(k -> {
//                    redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
//                    return redisTemplate.opsForZSet().range(k, 0, System.currentTimeMillis()).stream();
//                }).collect(Collectors.toList());
//
//        if (collect instanceof List) {
//            List objSet = (List<?>) collect;
//            return objSet;
//        }
//        return null;
//    }
//
//    /**
//     * 根据用户名查询 令牌相关信息
//     *
//     * @param page     分页信息
//     * @param username 用户名
//     * @return API调用结果
//     */
//    public ResultBean<Page> queryTokenByUsername(Page page, String username) {
//        String key = keyStrResolver.extract(
//                SecurityConstants.PROJECT_PREFIX + SecurityConstants.OAUTH_PREFIX + "uname_to_access_z:", StrUtil.COLON);
//
//        Object collect = redisTemplate.keys("*:" + username).stream().filter(k -> ((String) k).contains(key))
//                .flatMap(k -> {
//                    redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
//                    return redisTemplate.opsForZSet().range(k, 0, System.currentTimeMillis()).stream();
//                }).collect(Collectors.toList());
//
//        if (collect instanceof List) {
//            List objSet = (List<?>) collect;
//            page.setRecords(objSet);
//            page.setTotal(objSet.size());
//        }
//        return ResultBean.ok(page);
//    }
//
//
//    /**
//     * 使用游标 分页查询key
//     *
//     * @param patternKey key 通配符
//     * @param pageNum    当前页
//     * @param pageSize   每页大小
//     * @return 符合的 value列表
//     */
//    private List<String> findKeysForPage(String patternKey, long pageNum, long pageSize) {
//        ScanOptions options = ScanOptions.scanOptions().count(1000L).match(patternKey).build();
//        RedisSerializer<String> redisSerializer = (RedisSerializer<String>) redisTemplate.getKeySerializer();
//        Cursor cursor = (Cursor) redisTemplate.executeWithStickyConnection(
//                redisConnection -> new ConvertingCursor<>(redisConnection.scan(options), redisSerializer::deserialize));
//        List<String> result = new ArrayList<>();
//        int tmpIndex = 0;
//        long startIndex = (pageNum - 1) * pageSize;
//        long end = pageNum * pageSize;
//
//        assert cursor != null;
//        while (cursor.hasNext()) {
//            if (tmpIndex >= startIndex && tmpIndex < end) {
//                result.add(cursor.next().toString());
//                tmpIndex++;
//                continue;
//            }
//            if (tmpIndex >= end) {
//                break;
//            }
//            tmpIndex++;
//            cursor.next();
//        }
//        cursor.close();
//
//        return result;
//    }
//
//    private OAuth2AccessToken checkToken(String authHeader) {
//        Assert.state(StrUtil.isNotBlank(authHeader), "令牌为空");
//
//        String tokenValue = authHeader.replace(OAuth2AccessToken.BEARER_TYPE, StrUtil.EMPTY).trim();
//
//        OAuth2AccessToken accessToken = tokenStore.readAccessToken(tokenValue);
//        Assert.state(accessToken != null && StrUtil.isNotBlank(accessToken.getValue()), "令牌无效");
//        return accessToken;
//    }
//
//}
